<script lang="ts" setup>
import { useRouter } from 'vue-router';
import Header from '@/components/Header/Header.vue';
import { useI18n } from 'vue-i18n';
import { computed, ref, useTemplateRef } from 'vue';
import {
    EAnimateCSSUtil,
    EDropdown,
    EInput,
    EList,
    EProgress,
} from 'exploria-ui';
import { useSystemStore } from '@/stores/systemStore.ts';
import { ThemeEnum } from '@/types/global.d';

const { t } = useI18n();
const pathMap = import.meta.glob('@/views/document/pages/**/Document.vue');

// 优先级
const priority = [
    'vue',
    'basic',
    'layout',
    'geometry',
    'ai',
    'form',
    'data',
    'feedback',
    'navigation',
    'canvas',
    'echarts',
    'threejs',
    'advanced',
    'utils',
    'network',
    'optimize',
    'git',
];

const categoryMap = Object.keys(pathMap)
    .map(
        (path) =>
            path
                .split('/src/views/document/pages/')[1]!
                .split('/Document.vue')[0]!
                .replace('/', '.') as `${string}.${string}`, // 为了 i18n 匹配，将 / 替换为 .
    )
    .reduce(
        (map, routerName) => {
            const currCategory = routerName.split('.')[0]!;
            if (!map[currCategory]) map[currCategory] = [];
            map[currCategory].push({
                label: routerName,
                routerName,
            });
            return map;
        },
        {} as {
            [category: string]: {
                label: string;
                routerName: `${string}.${string}`;
            }[];
        },
    );

const router = useRouter();
const down = ref(false);
const routerTo = (routerName: `${string}.${string}`) => {
    router.push({ name: routerName });
};
const handleWheel = (e: WheelEvent) => {
    down.value = e.deltaY > 0;
};

const selected = computed(() => {
    return (routerName: `${string}.${string}`) => {
        if (router.currentRoute.value.path.includes('document')) {
            return (
                router.currentRoute.value.path
                    .split('/document/')[1]!
                    .replace('/', '.') === routerName
            );
        }
        return false;
    };
});
const searchText = ref('');

const tipsList = ref<
    {
        category: string;
        children: {
            label: string;
            routerName: `${string}.${string}`;
            targetClassName: string;
        }[];
    }[]
>([]);

const documentRef = useTemplateRef<HTMLElement>('document');

const goTo = (targetClassName: string, routerName: `${string}.${string}`) => {
    tipsList.value = [];
    searchText.value = '';
    const left = documentRef.value!.querySelector(
        '.document-main>.left-menu',
    ) as HTMLElement;
    const target = left.querySelector('.' + targetClassName) as HTMLElement;
    target.scrollIntoView({
        block: 'center',
        behavior: 'smooth',
    });
    routerTo(routerName);
    left.addEventListener(
        'scrollend',
        () => {
            EAnimateCSSUtil.once(target, 'animate__rubberBand');
        },
        {
            once: true,
        },
    );
};
const showLeftMenu = ref(false);
const systemStore = useSystemStore();
</script>
<template>
    <div class="document" ref="document" @wheel="handleWheel">
        <EProgress
            v-if="systemStore.currentTheme === ThemeEnum.PLAIN"
            :percentage="systemStore.percentage"
            style="position: fixed; width: 100%; height: 10px; top: 0; left: 0"
            #default="{ percentage }"
        >
            <span
                :style="{
                    fontSize: '8px',
                    opacity: percentage > 5 ? 1 : 0,
                    transition: 'opacity 0.3s ease',
                }"
            >
                {{ percentage.toFixed(2) + '%' }}
            </span>
        </EProgress>
        <Header v-model:more="showLeftMenu">
            <EDropdown
                placement="bottom-start"
                trigger="custom"
                :open-dropdown="tipsList.length > 0"
            >
                <EInput
                    style="
                        height: 30px;
                        border-radius: 3px;
                        border: none;
                        background-color: rgba(255, 255, 255, 0.5);
                    "
                    placeholder="请输入关键词"
                    type="text"
                    v-model="searchText"
                    @update:model-value="
                        () => {
                            tipsList = [];
                            if (searchText) {
                                for (const category in categoryMap) {
                                    const children = [];

                                    for (const obj of categoryMap[category]!) {
                                        if (t(obj.label).includes(searchText)) {
                                            children.push({
                                                ...obj,
                                                targetClassName:
                                                    obj.label.replace('.', '-'),
                                            });
                                        }
                                    }

                                    if (children.length > 0) {
                                        tipsList.push({ category, children });
                                    }
                                }
                            }
                        }
                    "
                    clearable
                >
                    <template #prefix>
                        <span class="iconfont icon-sousuo2" />
                    </template>
                </EInput>
                <template #dropdown>
                    <div
                        style="
                            background-color: white;
                            font-size: 14px;
                            user-select: none;
                        "
                    >
                        <div
                            v-for="(row, index) in tipsList"
                            :key="index"
                            style="
                                background-color: white;
                                font-size: 14px;
                                user-select: none;
                            "
                        >
                            <div
                                class="category"
                                style="
                                    color: rgba(0, 0, 0, 0.3);
                                    padding: 5px 0 0 5px;
                                    font-size: 12px;
                                "
                            >
                                {{ t(row.category) }}
                            </div>
                            <EList :data="row.children" style="color: red">
                                <template #row="{ row }">
                                    <div
                                        class="item"
                                        @click="
                                            goTo(
                                                row.targetClassName,
                                                row.routerName,
                                            );
                                            showLeftMenu = false;
                                        "
                                    >
                                        {{ t(row.label) }}
                                    </div>
                                </template>
                            </EList>
                        </div>
                    </div>
                </template>
            </EDropdown>
        </Header>
        <div class="document-main">
            <div
                class="left-menu"
                :style="{
                    transform: `translateX(${showLeftMenu ? '100%' : 0})`,
                }"
            >
                <div
                    class="category"
                    v-for="category of priority"
                    :key="category"
                >
                    <div class="title">{{ t(category) }}</div>
                    <div
                        class="item"
                        v-for="obj of categoryMap[category]"
                        :key="obj.label"
                        :class="[
                            obj.label.replace('.', '-'),
                            selected(obj.routerName) && 'selected',
                        ]"
                        @click="
                            () => {
                                showLeftMenu = false;
                                routerTo(obj.routerName);
                            }
                        "
                    >
                        {{ t(obj.label) }}
                    </div>
                </div>
            </div>
            <div class="right">
                <RouterView class="page" />
            </div>
        </div>
    </div>
</template>

<style scoped lang="scss">
@use '@/style/global' as global;
@import 'iconfont/iconfont.css';

.document {
    height: 100vh;
    width: 100vw;
    display: flex;
    flex-direction: column;
    // 蠕动渐变背景
    background-size: 200% 200%;
    animation: bg-position 15s ease infinite;
    background-image: linear-gradient(-45deg, #ffabab, #99bef6, #ffabab);

    // 渐变背景
    @keyframes bg-position {
        0%,
        100% {
            background-position: 0 0;
        }
        50% {
            background-position: 50% 50%;
        }
    }

    // 暗色主题
    @include global.useTheme(
        dark,
        (
            background-image: linear-gradient(-45deg, #d18e8e, #83a0cd, #d39090),
        )
    );

    // 朴素主题
    @include global.useTheme(
        plain,
        (
            background-image: none,
            background-color: #fff,
        )
    );

    // 手机主题
    @include global.useTheme(
        phone,
        (
            background-image: none,
            background-color: #fff,
        )
    );

    $box-shadow-at-phone:
        1px 1px 15px rgba(0, 0, 0, 0.3),
        inset 1px 1px 15px rgba(255, 255, 255, 0.5);

    .header {
        position: fixed;
        top: global.$gap;
        left: global.$gap;
        width: calc(100% - #{global.$gap} * 2);
        border: global.$border;
        box-shadow: $box-shadow-at-phone;
        background-color: global.$background-color;
        border-radius: global.$border-radius;
        backdrop-filter: global.$backdrop-filter;
        z-index: 2;
        // 朴素主题
        @include global.useTheme(
            plain,
            (
                backdrop-filter: none,
                position: static,
                width: 100%,
                border-radius: 0,
                box-shadow: none,
            )
        );
        // 手机主题
        @include global.useTheme(
            phone,
            (
                backdrop-filter: none,
                position: static,
                width: 100%,
                border-radius: 0,
                border-bottom: global.$block-border,
            )
        );
    }

    .document-main {
        flex: 1;
        display: flex;
        overflow: hidden;
        flex-direction: row;
        justify-content: space-between;

        @include global.useTheme(
            phone,
            (
                position: relative,
            )
        );

        .left-menu {
            overflow: auto;
            // 隐藏滚动条
            width: global.$document-aside-width;

            &::-webkit-scrollbar {
                @include global.useTheme(
                    phone,
                    (
                        width: 0,
                    )
                );

                @include global.useTheme(
                    light,
                    (
                        width: 0,
                    )
                );

                @include global.useTheme(
                    dark,
                    (
                        width: 0,
                    )
                );

                @include global.useTheme(
                    plain,
                    (
                        width: 7px,
                    )
                );
            }

            &::-webkit-scrollbar-thumb {
                @include global.useTheme(
                    plain,
                    (
                        background-color: #ededed,
                    )
                );
            }

            @include global.useTheme(
                phone,
                (
                    position: absolute,
                    z-index: 1,
                    left: -#{global.$document-aside-width},
                    transition: transform 0.3s,
                    height: 100%,
                )
            );

            @include global.useTheme(
                plain,
                (
                    scrollbar-width: unset,
                )
            );

            .category {
                background-color: global.$background-color;
                margin: global.$gap;
                box-shadow: global.$box-shadow;
                backdrop-filter: global.$backdrop-filter;
                border: global.$border;
                border-radius: global.$border-radius;
                overflow: hidden;
                @include global.useTheme(
                    plain,
                    (
                        margin: 0,
                        border-radius: 0,
                        box-shadow: none,
                        border: none,
                    )
                );

                &:first-child {
                    margin-top: calc(
                        #{global.$header-height} + #{global.$gap} * 2
                    );

                    @include global.useTheme(
                        plain,
                        (
                            border-top: none,
                            margin-top: 0,
                        )
                    );

                    @include global.useTheme(
                        phone,
                        (
                            margin-top: global.$gap,
                        )
                    );
                }

                @include global.useTheme(
                    plain,
                    (
                        backdrop-filter: none,
                    )
                );
                @include global.useTheme(
                    phone,
                    (
                        margin-top: global.$gap,
                        backdrop-filter: blur(20px),
                        background-color: rgba(255, 255, 255, 0.6),
                        box-shadow: $box-shadow-at-phone,
                    )
                );

                .title {
                    color: #333;
                    margin: 5px;
                    text-align: center;
                    font-size: 14px;
                    font-weight: bold;
                    @include global.useTheme(
                        plain,
                        (
                            text-align: start,
                            font-size: 17px,
                            margin: 8px,
                            margin-left: 10px,
                        )
                    );
                }

                .item {
                    color: #666;
                    padding: 5px;
                    margin: 10px;
                    font-size: 14px;
                    transition: background-color 0.1s;
                    cursor: pointer;
                    border-radius: global.$border-radius;

                    @include global.useTheme(
                        plain,
                        (
                            margin: 10px 20px,
                        )
                    );

                    &:hover {
                        background-color: rgba(153, 190, 246, 0.47);
                    }

                    &.selected {
                        color: #ffffff;
                        background-color: #99bef6;
                    }
                }
            }
        }

        .right {
            flex: 1;
            overflow: hidden;

            $footer-height: 251px;

            .page {
                min-height: calc(100% - $footer-height);
            }

            .footer {
                background-color: rgb(245, 247, 250);
                height: $footer-height;
            }
        }
    }
}
</style>
